﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Threading;
using System.Windows;

using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Geometry;
using ESRI.ArcGIS.Client.Symbols;
using ESRI.ArcGIS.Client.Tasks;
using ESRI.ArcGIS.Client.Toolkit;

namespace eGrid_App
{
    public sealed class MapLayersManager
    {

        #region delegates and events
        public delegate void MapLayerAddedDelegate(String aMapLayerID);
        public delegate void MapLayerDeletedDelegate(Layer aMapLayer);
        //public delegate void TicketSeverityChangedDelegate(int ticketID, int severity);

        public event MapLayerAddedDelegate MapLayerAdded;
        public event MapLayerDeletedDelegate MapLayerDeleted;
        //public event TicketSeverityChangedDelegate TicketSeverity;
        #endregion

        #region properties and instance variables
        /* Keep list of publically accessible map layers */
        
        private LayerCollection layers;
        
        public LayerCollection CloneLayers
        {
            get
            {
                LayerCollection outLayers = new LayerCollection(); 
                foreach (Layer layer in layers)
                {
                    Layer clone = CloneLayer(layer);
                    if (clone != null)
                        outLayers.Add(clone); 
                }
                return outLayers;
            }
        }

        public LayerCollection MapLayers
        {
            get
            {
                return layers;
            }
        }



        /* Keep track of all MapFrames currently active */
        //private List<MapFrame> mapFrames;
        //public Map backgroundMap {set; get;}

        private ArcGISTiledMapServiceLayer _streetLayer;
        private ArcGISTiledMapServiceLayer _imageryLayer;
        private ArcGISTiledMapServiceLayer _topoLayer;

        private GraphicsLayer _annotationsLayer;
        public GraphicsLayer annotationsLayer { get { return _annotationsLayer; } }

        //private FeatureLayer _serverVehicles;
        //private FeatureLayer _serverTickets;


        #endregion

        #region Constructors and setup

        public static MapLayersManager Instance { get; private set; }

        static MapLayersManager()
        {
            Instance = new MapLayersManager();
        }

        MapLayersManager()
        {
            layers = new LayerCollection();
            InitializeDefaultMapLayers();            
        }

        public void ResetDefaultLayers()
        {
            layers.Clear();
            InitializeDefaultMapLayers();
        }



        private void InitializeDefaultMapLayers()
        {
            _streetLayer = new ArcGISTiledMapServiceLayer();
            _streetLayer.ID = "StreetMap";
            _streetLayer.Opacity = 1;
            _streetLayer.Url = "http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer";
            AddLayer(_streetLayer);

            _imageryLayer = new ArcGISTiledMapServiceLayer();
            _imageryLayer.ID = "Imagery";
            _imageryLayer.Opacity = 1;
            _imageryLayer.Visible = false;
            _imageryLayer.Url = "http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer";
            AddLayer(_imageryLayer);

            _topoLayer = new ArcGISTiledMapServiceLayer();
            _topoLayer.ID = "ShadedRelief";
            _topoLayer.Opacity = 1;
            _topoLayer.Visible = false;
            _topoLayer.Url = "http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_ShadedRelief_World_2D/MapServer";
            AddLayer(_topoLayer);

            _annotationsLayer = new AnnotationMasterLayer();
            _annotationsLayer.Visible = true;
            _annotationsLayer.Opacity = 1;
            _annotationsLayer.ID = "AnnotationsLayer";
            AddLayer(_annotationsLayer);




        }

        #endregion

 

        #region Map Layers Management

        public void AddLayer(Layer newLayer)
        {
            layers.Add(newLayer);

            if (MapLayerAdded != null)
                MapLayerAdded(newLayer.ID);

        }

        public void AddLayer(string id, string url)
        {
            ArcGISTiledMapServiceLayer newLayer = new ArcGISTiledMapServiceLayer();
            newLayer.Url = url;
            newLayer.Visible = true;
            newLayer.Opacity = 1;
            newLayer.ID = id;

            layers.Add(newLayer);
            if (MapLayerAdded != null)
                MapLayerAdded(newLayer.ID);
        }

        public void RemoveLayer(string id)
        {
            foreach (Layer layer in layers)
            {
                if (layer.ID.Equals(id))
                {
                    layers.Remove(layer);

                    if (MapLayerDeleted != null)
                        MapLayerDeleted(layer);
                    break;
                }
            }
        }



        public Layer CloneLayer(Layer originalLayer)
        {

            if (typeof(ClonableLayer).IsAssignableFrom(originalLayer.GetType()))
            {
                // If the layer implements its own clone function, use this.
                return ((ClonableLayer)originalLayer).CloneLayer();
            }
            else if (originalLayer is ArcGISTiledMapServiceLayer)
            {
                ArcGISTiledMapServiceLayer cloneLayer = new ArcGISTiledMapServiceLayer();
                cloneLayer.Url = (originalLayer as ArcGISTiledMapServiceLayer).Url;
                cloneLayer.ID = (originalLayer as ArcGISTiledMapServiceLayer).ID;
                cloneLayer.Opacity = (originalLayer as ArcGISTiledMapServiceLayer).Opacity;
                cloneLayer.Visible = originalLayer.Visible;
                return cloneLayer;
            }
            else if (originalLayer is ArcGISDynamicMapServiceLayer)
            {
                ArcGISDynamicMapServiceLayer cloneLayer = new ArcGISDynamicMapServiceLayer();
                cloneLayer.Url = (originalLayer as ArcGISDynamicMapServiceLayer).Url;
                cloneLayer.ID = (originalLayer as ArcGISDynamicMapServiceLayer).ID;
                cloneLayer.Opacity = (originalLayer as ArcGISDynamicMapServiceLayer).Opacity;
                cloneLayer.Visible = originalLayer.Visible;
                return cloneLayer;
            }
            else if (originalLayer is FeatureLayer)
            {
                 FeatureLayer cloneLayer = new FeatureLayer();
                 cloneLayer.Url = (originalLayer as FeatureLayer).Url;
                 cloneLayer.ID = (originalLayer as FeatureLayer).ID;
                 cloneLayer.Opacity = (originalLayer as FeatureLayer).Opacity;
                 cloneLayer.Visible = originalLayer.Visible;
                 return cloneLayer;
            }
            else if (originalLayer is GraphicsLayer)
            {
                GraphicsLayer cloneLayer = new GraphicsLayer();
                cloneLayer.ID = (originalLayer as GraphicsLayer).ID;
                cloneLayer.Opacity = (originalLayer as GraphicsLayer).Opacity;
                cloneLayer.Visible = originalLayer.Visible;
                DeepCopyGraphics((originalLayer as GraphicsLayer), cloneLayer);
                return cloneLayer;
            }
            else
                return null;
        }


        public Layer Clonelayer(String layerID)
        {
            foreach (Layer layer in layers)
            {
                if (layer.ID == layerID)
                {
                    return CloneLayer(layer);
                }
            }
            return null; 
        }


        // Makes a deep copy of each Graphic in the originalLayer, and adds it to the supplied cloneLayer.
        public void DeepCopyGraphics(GraphicsLayer originalLayer, GraphicsLayer cloneLayer)
        {
            foreach (Graphic g in originalLayer.Graphics)
            {
                Graphic newGraphic = new Graphic();
                newGraphic.Symbol = g.Symbol;
                newGraphic.Geometry = Geometry.Clone(g.Geometry);
                cloneLayer.Graphics.Add(newGraphic);
            }
        }

        #endregion


    }



}
